//======================================================================================
//  Apache License, Version 2.0
//  Notes:Use this command to anonymously check out the latest project source code:
//  Non-members may check out a read-only working copy anonymously over HTTP.
//  SVN checkout http://YHHLineCommandWsp.googlecode.com/svn/trunk/ 
//
//  Author:		Kevin Yang
//  Email:		Bigearrabbit@qq.com
//
//  DATE:		2013-4-7
//
//  File Name:	YHHLineCommandCore.cpp
//
//  Notes:
//
//======================================================================================
//Local Framework
#include "YHHLineCommandCore.h"
#include "YHHCatiaBaseDefine.h"
#include "YHHILineCommandFactory.h"

//local Framework
#include "YHHILineCommandChild.h"

// ApplicationFrame Framework
#include "CATFrmEditor.h"                 // needed to retrieve the editor and then to highight objects

// ObjectModelerBase Framework
#include "CATIContainer.h"                // needed to create a GS (Geometrical Set)

// ObjectSpecsModeler Framework
#include "CATISpecObject.h"               // needed to manage feature
#include "CATIDescendants.h"              // needed to aggregate the newly created Line Create By GSD

// InteractiveInterfaces
#include "CATIBuildPath.h"                // needed to build a path element to highlight a feature

// MechanicalModeler Framework
#include "CATIMechanicalRootFactory.h"    // needed to create a GS 
#include "CATIGSMTool.h"                  // GSMTool and HybridBody features
#include "CATIBasicTool.h"                // To retrieve the current tool
#include "CATIMmiGeometricalSet.h"        // Only for GSMTool feature
#include "CATIMmiNonOrderedGeometricalSet.h"  // Only for GS feature

// MechanicalModelerUI Framework
#include "CATPrtUpdateCom.h"              // needed to update the feature according to the user's update settings
#include "CATMmrLinearBodyServices.h"     // To insert in ordered and linear body

// MecModInterfaces Framework
#include "CATIPrtPart.h"                  // needed to look for a GSM tool
#include "CATMfBRepDefs.h"                // needed to declare the modes of BRep feature creation

// Visualization Framework
#include "CATPathElement.h"               // needed to highlight objects
#include "CATHSO.h"                       // needed to highlight objects    
#include "CATIVisProperties.h"            // needed to change Line Create By GSD's graphical appearance
#include "CATVisPropertiesValues.h"
#include "iostream.h"					//need for CAA iostream.not c++  

//System framework
#include "CATGetEnvValue.h"               // To define the type of development
#include "CATBoolean.h"
#include "CATLib.h"

// This command is used by a CATCommandheader
#include "CATCreateExternalObject.h" 

CATImplementClass( YHHLineCommandCore,
                   Implementation, 
                   CATBaseUnknown,
                   CATNull );
 
//-----------------------------------------------------------------------------
YHHLineCommandCore::YHHLineCommandCore()
: CATBaseUnknown()
, m_CurrentElt(NULL_var)
, m_MyFeature(NULL_var)
, m_pParamChild(NULL)
{
}
//-----------------------------------------------------------------------------
YHHLineCommandCore::~YHHLineCommandCore()
{
}
//-----------------------------------------------------------------------------
YHHLineCommandCore::YHHLineCommandCore(YHHLineCommandCore& original):
   CATBaseUnknown(original)
{
}
//-----------------------------------------------------------------------------
YHHLineCommandCore& YHHLineCommandCore::operator=(YHHLineCommandCore& original)
{
   CATBaseUnknown::operator=(original);
   return *this;
}
//-----------------------------------------------------------------------------
HRESULT YHHLineCommandCore::Create()
{
	cout <<"I am in YHHLineCommandCore::Create" << endl;
	m_MyFeature = NULL_var;//clear first
	if (NULL == m_pParamChild)return E_INVALIDARG;//param pointer check
	if (NULL == m_pEditor)return E_INVALIDARG;//editor pointer check

	HRESULT rc = E_FAIL ;

	//
	// 1- Looking for a body to create the Line Create By GSD
	//    
	// 

	// CATIGSMTool is implemented by the HybridBody and GSMTool StartUp
	// it is a valid pointer to handle the body which will contain the new
	// Line Create By GSD
	//
	CATIGSMTool * piGSMTool = NULL ;

	char * pLineCommandOGS = NULL ;
	CATLibStatus result = ::CATGetEnvValue("YHHLineCommandChildOGS",&pLineCommandOGS);  
	if ( (CATLibError == result) || ( NULL == pLineCommandOGS) )
	{
		char * pLineCommandNoHybridBody = NULL ;
		result = ::CATGetEnvValue("YHHLineCommandChildNoHybridBody",&pLineCommandNoHybridBody); 
		if ( (CATLibError == result) || ( NULL == pLineCommandNoHybridBody) )
		{
			// Looking for or creating only a Geometrical Set
			// The result cannot be an ordered geometrical set or an hybrid body
			// 
			rc = LookingForGeomSet(&piGSMTool);
		}else
		{
			free (pLineCommandNoHybridBody) ;
			pLineCommandNoHybridBody = NULL ;

			// Looking for an OGS or a GS, or creating a Geometrical Set
			// The result cannot be an hybrid body
			//
			rc = LookingForGeomSetOrOrderedGeomSet(&piGSMTool);   
		}
	}else
	{
		free (pLineCommandOGS) ;
		pLineCommandOGS = NULL ;

		// Looking for any type of mechanical bodies, or creating a Geometrical Set
		// The result cannot be a former solid body
		//
		rc = LookingForAnyTypeOfBody(&piGSMTool);       
	}

	//
	// 2- Creating the Line Create By GSD
	// 
	CATISpecObject * piSpecOnLineCommand = NULL ;

	if ( SUCCEEDED(rc) && ( NULL != piGSMTool) )
	{   
		// 
		// Uses YHHILineCommandFactory implemented by CATPrtCont
		// 
		CATISpecObject_var piSpecObjOnTool = piGSMTool ;
		if (!piSpecObjOnTool) //check pointer
		{
			cout<<"Error : piSpecObjOnTool is NULL."<<endl;
			rc = E_FAIL ;//find error 
			goto endOfStep2;//finish step 2
		}

		// GetFeatContainer for a mechanical feature
		// is CATPrtCont, the specification container
		CATIContainer_var spContainer = piSpecObjOnTool->GetFeatContainer();  
		if (!spContainer) //check pointer
		{
			cout<<"Error : spContainer is NULL."<<endl;
			rc = E_FAIL ;//find error 
			goto endOfStep2;//finish step 2
		}
	
		//get YHHILineCommandFactory fatory
		YHHILineCommandFactory * piLineCommandFactory = NULL;//factory
		rc = spContainer->QueryInterface( IID_YHHILineCommandFactory , (void**)& piLineCommandFactory );
		if (FAILED(rc)) //check result
		{
			cout<<"Error : piLineCommandFactory is NULL."<<endl;
			goto endOfStep2;//finish step 2
		}

		// creates the Line Create By GSD
		YHHILineCommandChild * pLineCommand = NULL;
		rc = piLineCommandFactory->CreateYHHILineCommand(&pLineCommand,m_pParamChild);
		if (FAILED(rc)) //check result
		{
			cout<<"Error : pLineCommand is NULL."<<endl;
			goto endOfStep2;//finish step 2
		}
		rc = piSpecOnLineCommand->QueryInterface(IID_CATISpecObject,(void **) &piSpecOnLineCommand );
		YHHRelease(pLineCommand);//release
		if (FAILED(rc)) //check result
		{
			cout<<"Error : piSpecOnLineCommand is NULL."<<endl;
			goto endOfStep2;//finish step 2
		}
		m_MyFeature = piSpecOnLineCommand;//record 
	}
endOfStep2://end of step 2

	//
	// 3- Aggregating the newly Line Create By GSD in the Geometrical Set
	// 
	if ( SUCCEEDED(rc) && (NULL != piGSMTool) && (NULL !=piSpecOnLineCommand) )
	{
		CATIDescendants * pIDescendantsOnGSMTool = NULL ;
		rc = piGSMTool->QueryInterface(IID_CATIDescendants, (void**) & pIDescendantsOnGSMTool);
		if ( SUCCEEDED(rc) )
		{
			// Checks the type of the GSMTool
			// 
			int TypeOrderedBody = -1 ;
			piGSMTool->GetType(TypeOrderedBody);

			if ( 1 == TypeOrderedBody )
			{  // OGS/HB : the CC is set after the current feature or at the end
				//       of the set, if the current feature is the set itself
				//
				cout <<" Ordered and linear body " << endl;
				int pos = 0 ;
				if ( NULL_var != m_CurrentElt)
				{
					pos = pIDescendantsOnGSMTool->GetPosition(m_CurrentElt);                   
				}

				if ( 0 == pos )
				{
					// The current feature is the GSMTool itself
					// the CC is appended at the end
					pIDescendantsOnGSMTool->Append(piSpecOnLineCommand);
				}else
				{
					// the current feature is inside the GSMTool
					// the CC is appended just below it (which can be at the end)
					pIDescendantsOnGSMTool->AddChild(piSpecOnLineCommand,pos+1);
				}
			}else
			{  // GS : the CC is set at the end of the set
				cout <<" GS case " << endl;
				pIDescendantsOnGSMTool->Append(piSpecOnLineCommand);
			}

			pIDescendantsOnGSMTool->Release();
			pIDescendantsOnGSMTool = NULL ;
		}
	}

	if ( NULL != piGSMTool )
	{
		piGSMTool->Release();
		piGSMTool = NULL ;
	}

	if ( NULL != piSpecOnLineCommand )
	{
		piSpecOnLineCommand->Release();
		piSpecOnLineCommand = NULL ;
	}

	return rc ;
}

//-----------------------------------------------------------------------------
HRESULT YHHLineCommandCore::CreateTool(CATIPrtPart * pIPrtPart, CATIGSMTool ** pIGsmTool)
{
	if ( ( pIGsmTool == NULL) || ( NULL == pIPrtPart ) )
	{
		return E_FAIL ;
	}

	*pIGsmTool  = NULL ;

	HRESULT rc = E_FAIL ;

	CATISpecObject * pISpecOnPart = NULL ;
	rc = pIPrtPart->QueryInterface(IID_CATISpecObject,(void**) &pISpecOnPart) ;
	if ( SUCCEEDED(rc) )
	{

		// GetFeatContainer for a mechanical feature
		// is CATPrtCont, the specification container
		CATIContainer_var spContainer = pISpecOnPart->GetFeatContainer();  
		if ( NULL_var != spContainer )
		{
			// 
			CATIMechanicalRootFactory * pMechanicalRootFactory = NULL;
			rc = spContainer->QueryInterface( IID_CATIMechanicalRootFactory , 
				( void**)& pMechanicalRootFactory );
			if ( SUCCEEDED(rc) )
			{
				// creates a new GS aggregated by the Part feature
				CATISpecObject_var spiSpecOnGSMTool;
				rc = pMechanicalRootFactory->CreateGeometricalSet( "" , pIPrtPart,spiSpecOnGSMTool);

				pMechanicalRootFactory->Release();
				pMechanicalRootFactory = NULL ;

				if ( NULL_var != spiSpecOnGSMTool )
				{
					spiSpecOnGSMTool->QueryInterface(IID_CATIGSMTool, (void**) &(*pIGsmTool));
				}
			}
		}

		pISpecOnPart->Release();
		pISpecOnPart = NULL ;

	}

	return rc ;
}
//---------------------------------------------------------
HRESULT YHHLineCommandCore::ExtractParams(YHHILineCommandChild *ipInstance,YHHLineCommandChildParam & oParam)
{
	// Reads the inputs of the Line Command.
	HRESULT rc = S_OK;
	rc = ipInstance->GetParams(oParam) ;
	oParam.SelfSpecObject = (YHHILineCommandChild_var)ipInstance;//record self Spec
	return rc;//return
}
//---------------------------------------------------------
HRESULT YHHLineCommandCore::LookingForGeomSet(CATIGSMTool ** piGsmtool)
{
	if ( (NULL == piGsmtool) || (NULL ==m_pEditor) ) return E_FAIL ;

	HRESULT rc= E_FAIL ;

	*piGsmtool = NULL ;

	// Retrieves the Part feature which holds the current tool
	// 
	CATIPrtPart * pIPrtPart = NULL ;
	CATPathElement PathAct = m_pEditor->GetUIActiveObject();
	rc = PathAct.Search(IID_CATIPrtPart,(void**)&pIPrtPart) ;

	if ( SUCCEEDED(rc) && ( NULL!=pIPrtPart) )
	{
		CATBoolean ToolToCreate = TRUE ;

		CATIBasicTool_var CurrentTool ;
		CurrentTool = pIPrtPart->GetCurrentTool() ;

		if ( NULL_var != CurrentTool )
		{
			// is it a GS ?
			CATIMmiNonOrderedGeometricalSet * pIGSOnCurrentTool = NULL ;
			rc = CurrentTool->QueryInterface(IID_CATIMmiNonOrderedGeometricalSet, 
				(void**) &pIGSOnCurrentTool);
			if ( SUCCEEDED(rc) )
			{
				// Ok we have found a valid geometrical set
				ToolToCreate = FALSE ;

				rc = pIGSOnCurrentTool->QueryInterface(IID_CATIGSMTool, (void**) piGsmtool);

				pIGSOnCurrentTool->Release();
				pIGSOnCurrentTool = NULL ;

			}
		}

		if ( TRUE == ToolToCreate )
		{
			rc = CreateTool(pIPrtPart,piGsmtool);
		}
	}

	if ( NULL != pIPrtPart )
	{
		pIPrtPart->Release();
		pIPrtPart = NULL ;
	}

	return rc ;
}
//-----------------------------------------------------------------------------
HRESULT YHHLineCommandCore::LookingForGeomSetOrOrderedGeomSet(CATIGSMTool ** piGsmtool)
{
	if ( (NULL == piGsmtool) || (NULL ==m_pEditor) ) return E_FAIL ;

	HRESULT rc= E_FAIL ;

	*piGsmtool = NULL ;

	CATIPrtPart * pIPrtPart = NULL ;
	CATPathElement PathAct = m_pEditor->GetUIActiveObject();

	rc = PathAct.Search(IID_CATIPrtPart,(void**)&pIPrtPart)  ;

	if ( SUCCEEDED(rc) && ( NULL!=pIPrtPart) )
	{
		CATBoolean ToolToCreate = TRUE ;  

		CATIBasicTool_var CurrentTool ;
		CurrentTool = pIPrtPart->GetCurrentTool() ;

		if ( NULL_var != CurrentTool )
		{
			// is it a GSMTool ?
			CATIMmiGeometricalSet * pIGSMToolOnCurrentTool = NULL ;
			rc = CurrentTool->QueryInterface(IID_CATIMmiGeometricalSet, (void**) &pIGSMToolOnCurrentTool);
			if ( SUCCEEDED(rc) )
			{
				// Ok we have found a valid geometrical set ( ordered or not )
				ToolToCreate = FALSE ;

				rc = pIGSMToolOnCurrentTool->QueryInterface(IID_CATIGSMTool, (void**) piGsmtool);

				pIGSMToolOnCurrentTool->Release();
				pIGSMToolOnCurrentTool = NULL ;
			}
		}

		if ( (TRUE == ToolToCreate) )
		{
			rc = CreateTool(pIPrtPart,piGsmtool);
		}

	}

	if ( NULL != pIPrtPart )
	{
		pIPrtPart->Release();
		pIPrtPart = NULL ;
	}

	return rc ;
}
//-----------------------------------------------------------------------------
HRESULT YHHLineCommandCore::LookingForAnyTypeOfBody(CATIGSMTool ** piGsmtool)
{
	if ( (NULL == piGsmtool) || (NULL ==m_pEditor) ) return E_FAIL ;

	HRESULT rc= E_FAIL ;

	*piGsmtool = NULL ;

	CATIPrtPart * pIPrtPart = NULL ;
	CATPathElement PathAct = m_pEditor->GetUIActiveObject();

	rc = PathAct.Search(IID_CATIPrtPart,(void**)&pIPrtPart)  ;

	if ( SUCCEEDED(rc) && ( NULL!=pIPrtPart) )
	{
		CATBoolean ToolToCreate = TRUE ;  

		CATIBasicTool_var CurrentTool ;
		CurrentTool = pIPrtPart->GetCurrentTool() ;

		if ( NULL_var != CurrentTool )
		{
			// is it a GSMTool or an hybrid body ?
			CATIGSMTool * pIGSMToolOnCurrentTool = NULL ;
			rc = CurrentTool->QueryInterface(IID_CATIGSMTool, (void**) &pIGSMToolOnCurrentTool);
			if ( SUCCEEDED(rc) )
			{
				// Ok we have found a valid body
				ToolToCreate = FALSE ;

				*piGsmtool = pIGSMToolOnCurrentTool ;
			}
		}

		if ( TRUE == ToolToCreate )
		{
			rc = CreateTool(pIPrtPart,piGsmtool);
		}

	}

	if ( NULL != pIPrtPart )
	{
		pIPrtPart->Release();
		pIPrtPart = NULL ;
	}

	return rc ;
}
//---------------------------------------------------------
